home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
ALIAS.ZIP
/
ALIASWC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-09
|
31KB
|
1,116 lines
/*
Scaling, Rotation, Antialiasing prototyper. revision 3.
This program was written by Lewis A. Sellers (Minimalist)
of The Minimalist Group, and the MOSOCI Grail Project in
1995-1996 Anno Dominus.
While it is the result of several days of work on my part, fiddled
with here and there over a few months as time permits, you can use
it and the code involved if you wish as intas you include the standard
greetings to me somewhere in your program, say in the credits.
You must supply a BMP filename as an argument such as:
C:> ALIAS DEATH.BMP
The BMP can be any size, grayscale or color, so long as it is 8-bit color.
This originally was written with borland turbo c++ 3.0 simply because it
was easy to do so. To get a speed increase I tried using Borland C++ 4.52
which I bought a while back. Most of the new Borland stuff is much more
complicated than needs be so I hadn't used it much, but I did get about an
extra two FPS from the recompile.
I also wrote a pascal version while teaching myself pascal on the IBMs.
This is the 32-bit WATCOM version. While there is an older Borland 16-bit
version (aliasc.c) and a Turbo Pascal version (aliaspas.pas) this is the
only one that is currently being revised and improved.
This program is designed for at least the 486 processors. Preferably pentiums.
Probably it'll end up as some kind of tutorial one day.
PLEASE READ ALIAS.TXT
--MIN (rhymes with NIN)
"the me that you know is now made up of wires
and even when i'm right with you i'm so far away" --NIN
*/
#include <stdlib.h>
#include <conio.h>
#include <malloc.h>
#include <stdio.h>
#include <time.h>
#include <dos.h>
#include <math.h>
#include <mem.h>
//general defines
#define FALSE (1==0)
#define TRUE (1==1)
#define FAILURE 0
#define SUCCESS 1
typedef unsigned char byte;
typedef unsigned short int word;
typedef unsigned int dword;
//prototypes
void change_timer(void);
void restore_timer(void);
void mode_graphic(void);
void mode_text(void);
int LoadTestImage(char *name);
void setup_fps(void);
void print_fps(int fps);
void bilinear(void);
void trilinear(void);
void hyperlinear(void);
void color_bilinear(void);
void color_trilinear(void);
void color_hyperlinear(void);
void copycomposite(void);
void clearcomposite(void);
//int lines(void);
//TIMER
#define PIT_FREQUENCY 0x1234DDL
#define frequency 100
#define counter PIT_FREQUENCY/frequency
volatile int BIOS_ticks=0;
volatile int second_ticks=0;
volatile int second_flag=FALSE;
void (__interrupt __far *prev_int_1c)();
void __interrupt __far timerhandler()
{
BIOS_ticks+=counter;
second_ticks++;
if(BIOS_ticks>=0x10000) {
BIOS_ticks=0;
_chain_intr(prev_int_1c);
}
if(second_ticks>=100) {
second_flag=TRUE;
second_ticks=0;
}
outp(0x20,0x20);
}
void change_timer()
{
//swap out the BIOS handler for our own....
prev_int_1c=_dos_getvect(0x1c);
_dos_setvect(0x1c,timerhandler);
//change the clock frequency to 100 per second
outp(0x43,0x34);
outp(0x40,(byte)(counter%256));
outp(0x40,(byte)(counter/256));
}
void restore_timer()
{
//restore 18.2 frequency of PIT 0
outp(0x43,0x34);
outp(0x40,0);
outp(0x40,0);
//restore the BIOS tick handler
_dos_setvect(0x1c,timerhandler);
}
//constant
#define WIDTH 320
#define HEIGHT 200
#define WIDTH_CENTER 160
#define HEIGHT_CENTER 100
#define WIDTH_OFFSET 60
#define HEIGHT_OFFSET 0
#define W_WIDTH 200
#define W_HEIGHT 200
#define W_WIDTH_CENTER 100
#define W_HEIGHT_CENTER 100
#define W_LEFT 60
#define W_RIGHT 260
#define W_TOP 0
#define W_BOTTOM 200
#define T_WIDTH 256
#define T_HEIGHT 256
#define T_WIDTH_CENTER 128
#define T_HEIGHT_CENTER 128
#define T_LEFT 0
#define T_RIGHT 256
#define T_TOP 0
#define T_BOTTOM 256
char *G_BASE=(char *)(0xa0000); //graphics memory
//GRAPHICS
#define PI 3.14159
char *texture;
int *y320;
char *composite;
struct rgb_struct {
byte red;
byte green;
byte blue;
} *palette;
byte *palette_matrix;
typedef struct {
//fileformat
word type; //42 4d BM
dword filesize; //36 fe
word unused1;
word unused2;
dword offsetbits; //0c
//info
dword infosize;
word width; //c8 00
word w1;
word height;
word h1;
word planes; //1
byte bitcount; //8
dword compression; //0
dword imagesize; //00 00 fa 00
dword xpels;
dword ypels;
dword colorsused;
dword colorsimportant;
byte u1;
} bmp_struct;
//
void mode_graphic(void);
#pragma aux mode_graphic = \
"mov ax,13h" \
"int 10h" \
"mov dx,03c2h" \
"mov al,0e3h" \
"out dx,al" /* put it in square mode */ \
"mov dx,0x3c6" \
"mov ax,0xff" \
"out dx,al" \
"mov dx,0x3c8" \
"mov al,0" \
"out dx,al" \
"mov dx,0x3c9" \
"mov esi, [palette]" \
"mov ecx,768" \
"mgloop:" \
"mov al,[esi]" \
"out dx,al" \
"inc esi" \
"sub ecx,1" \
"jnz mgloop" \
modify [ax dx esi];
void mode_text(void);
#pragma aux mode_text = \
"mov ax,3" \
"int 10h" \
modify [ax];
//load in a grayscale 320x200 BMP
int LoadTestImage(char *name)
{
FILE *bmp;
int x,y;
int n;
byte *thrash;
bmp_struct *bf;
char *source,*destination;
int w,h,w_src,h_src,w_dst,h_dst;
int BWIDTH;
struct rgba_struct {
byte blue;
byte green;
byte red;
byte alpha;
} *temp_palette;
//
bmp=fopen(name,"rb");
if(bmp==NULL) return FAILURE;
//
bf=(bmp_struct *)malloc(sizeof(bmp_struct));
if(bf==NULL) {
mode_text();
// printf("Not enough memory (%lu) for BMP header.\n",farcoreleft());
exit(FAILURE);
}
fread(bf,sizeof(bmp_struct),1,bmp);
if(bf->bitcount!=8) {
mode_text();
printf("The bitmap must be 8-bit (256 color).\n");
exit(FAILURE);
}
//PALETTE
//from b-g-r-unused dword format to proper RGB 3byte.
temp_palette=(void *)malloc(4*256);
if(temp_palette==NULL) {
mode_text();
// printf("Not enough memory (%lu) for temp palette.\n",farcoreleft());
exit(FAILURE);
}
fread(temp_palette,4*256,1,bmp);
for(n=0;n<256;n++)
{
palette[n].red=(temp_palette[n].red>>2);
palette[n].green=(temp_palette[n].green>>2);
palette[n].blue=(temp_palette[n].blue>>2);
}
free(temp_palette);
//TEXTURE
//blackout texture
memset(texture,0,T_WIDTH*T_HEIGHT);
//thrash the dumb MS format...
thrash=(byte *)malloc(bf->width*bf->height);
if(thrash==NULL) {
mode_text();
// printf("Not enough memory (%lu) for temporary bitmap thrashing area.\n",farcoreleft());
exit(FAILURE);
}
fread(thrash,bf->width*bf->height,1,bmp);
//dword align
if((bf->width&3)!=0)
BWIDTH=bf->width+(4-(bf->width&3));
else
BWIDTH=bf->width;
//compute picture along x
w_src=0;
w_dst=0;
w=bf->width;
if(w>T_WIDTH) { w_src=((w-T_WIDTH)>>1); w=T_WIDTH; }
if(w<T_WIDTH) w_dst=(T_WIDTH-w)>>1;
//compute along y
h_src=0;
h_dst=0;
h=bf->height;
if(h>T_HEIGHT) { h_src=((h-T_HEIGHT)>>1); h=T_HEIGHT; }
if(h<T_HEIGHT) h_dst=((T_HEIGHT-h)>>1);
//
source=thrash+((bf->height-1)*BWIDTH)+w_src-(h_src*BWIDTH);
destination=texture+w_dst+h_dst*T_WIDTH;
for(y=0;y<h;y++)
{
memcpy(destination,source,w);
source-=BWIDTH;
destination+=T_WIDTH;
}
free(thrash);
free(bf);
fclose(bmp);
return SUCCESS;
}
//fps
byte fpsset[8][24]={
" ###### ###### #### ",
" # # # # # ",
" # # # # ",
" ##### ###### #### ",
" # # # ",
" # # # ",
" # # # # ",
" # # #### "
};
byte charset[10][8][8]={
//0
{" ##### ",
" # #",
" # #",
" # #",
" # #",
" # #",
" ##### ",
" "},
//1
{" ## ",
" # ",
" # ",
" # ",
" # ",
" # ",
" ###",
" "},
//2
{" #### ",
" # #",
" #",
" ### ",
" # ",
" # #",
" ##### ",
" "},
// 3
{" ##### ",
" # #",
" #",
" #### ",
" #",
" # #",
" ##### ",
" "},
//4
{" ## ",
" # # ",
" # # ",
" ###### ",
" # ",
" # ",
" ### ",
" "},
//5
{" #######",
" # ",
" # ",
" ###### ",
" #",
" # #",
" ##### ",
" "},
//6
{" ##### ",
" # ",
" # ",
" ###### ",
" # #",
" # #",
" ##### ",
" "},
//7
{" ######",
" # #",
" # ",
" # ",
" # ",
" # ",
" # ",
" "},
//8
{" ##### ",
" # #",
" # #",
" ##### ",
" # #",
" # #",
" ##### ",
" "},
//9
{" ##### ",
" # #",
" # #",
" ######",
" #",
" # ",
" #### ",
" "}
};
//setup the fps counter...
void setup_fps()
{
int c,x,y;
byte *vid=(byte *)composite+(8*WIDTH);
//change the 0 to 9 charset from spaces and pound-signs
//into 0 and 255 (ie, black and white).
for(c=0;c<=9;c++)
for(y=0;y<=7;y++)
for(x=0;x<=7;x++)
if(charset[c][y][x]=='#')
charset[c][y][x]=255;
else
charset[c][y][x]=0;
//draw a "FPS" right below where the fps will be.
//yes, it's slow C code, but here that's ok.
for(y=0;y<=7;y++)
for(x=0;x<=23;x++)
if(fpsset[y][x]=='#')
vid[y*WIDTH+x]=255;
else
vid[y*WIDTH+x]=0;
}
//draw a counter number at the top left of the graphics screen
void print_fps(int fps)
{
int digits=6;
char s[16];
int count=0;
word x_offset=0;
int c,x,y;
byte *src,*dst;
//
sprintf(s,"%d",fps);
//
while((s[count]!=NULL)&&(count<digits)) {
c=(s[count++]-'0');
src=(byte *)charset+c*8*8;
dst=(byte *)composite+x_offset;
for(y=0;y<8;y++) {
for(x=0;x<8;x++) {
*dst=*src;
dst++;
src++;
}
dst+=WIDTH-8;
}
x_offset+=8;
}
//ok. we wrote out the digits. now cleanup anything left over from the
//last time on the right. we assume no more than 6 digits MAX.
dst=(char *)composite+x_offset;
for(y=0;y<8;y++) {
for(x=x_offset;x<digits*8;x++) {
*dst++=0;
}
dst+=WIDTH-((digits*8)-x_offset);
}
}
void show_colors(void)
{
byte *p;
int n,w;
//display the color palette for us under the "fps"
p=(byte *)composite+WIDTH*16;
for(n=0;n<64;n++,p+=WIDTH) {
for(w=0;w<8;w++) {
*(p+w)=n;
*(p+w+8)=n+64;
*(p+w+16)=n+128;
*(p+w+24)=n+192;
}
}
//show us the bilinear antialiasing matrix column0. It SHOULD be an
//exact match to the color palette. :)
p=(byte *)composite+WIDTH*(32+64);
for(n=0;n<64;n++,p+=WIDTH) {
for(w=0;w<8;w++) {
*(p+w)=palette_matrix[n];
*(p+w+8)=palette_matrix[n+64];
*(p+w+16)=palette_matrix[n+128];
*(p+w+24)=palette_matrix[n+192];
}
}
}
//this is the fixed-point version of the scaling/rotation routine.
//since we want maximum speed while still remaining in C parts of this
//may be hard to read compared to the general rotate/scale routine.
//It is similiar to the mathematical version except it uses 16.16
//fixed-point and computes an initial texture vector then does something
//similiar to a two-level line drawing routine, ok?
void FixedRotateScale(float scale, //the scaling factor
float angle) //the rotation angle
{
int sinas=sin(-angle)*65536*scale;
int cosas=cos(-angle)*65536*scale;
//x' = cos(-angle)+sin(-angle)
//y' = cos(-angle)-sin(-angle)
int xc=T_WIDTH_CENTER*65536 - (W_HEIGHT_CENTER*(cosas+sinas));
int yc=T_HEIGHT_CENTER*65536 - (W_WIDTH_CENTER*(cosas-sinas));
int tx,ty;
int x,y;
int tempx,tempy;
char *screen=composite+WIDTH_OFFSET+HEIGHT_OFFSET*WIDTH;
for (y=0;y<W_HEIGHT;y++)
{
tx=xc; ty=yc;
for(x=0;x<W_WIDTH;x++)
{
tempx=(tx>>16); tempy=(ty>>16);
if( (tempx<T_LEFT) || //clip
(tempx>=T_RIGHT) ||
(tempy<T_TOP) ||
(tempy>=T_BOTTOM) )
screen[x]=0; //clip to black
else
screen[x]=texture[tempx+tempy*T_WIDTH]; //draw texel
tx+=cosas; ty-=sinas;
}
screen+=WIDTH; xc+=sinas; yc+=cosas;
}
}
//this is the revised floating-point version of the scaling/rotation routine.
//now that I finally have a cpu that actually supports FPU op-code
//(from a 486sx25 to a 486dx4-100) thought I'd try them out.
//note that unlike the pure mathematical version, we compute the vector
//of rotation just once at the beginning of the function.
void FloatRotateScale(float scale, //the scaling factor
float angle) //the rotation angle
{
float sinas=sin(-angle)*scale;
float cosas=cos(-angle)*scale;
//x' = cos(-angle)+sin(-angle)
//y' = cos(-angle)-sin(-angle)
float xc=T_WIDTH_CENTER - (W_HEIGHT_CENTER*(cosas+sinas));
float yc=T_HEIGHT_CENTER - (W_WIDTH_CENTER*(cosas-sinas));
float tx, ty;
int x,y;
//actually to composite buffer and not to screen...
//but it can be changed easily.
char *screen=composite+WIDTH_OFFSET+HEIGHT_OFFSET*WIDTH;
for (y=0;y<W_HEIGHT;y++)
{
tx=xc; ty=yc;
for (x=0;x<W_WIDTH;x++)
{
if( (tx<(float)T_LEFT) ||
(tx>=(float)T_RIGHT) ||
(ty<(float)T_TOP) ||
(ty>=(float)T_BOTTOM) )
screen[x]=0;
else
screen[x]=texture[(int)(tx)+(((int)ty)*T_WIDTH)];
tx+=cosas; ty-=sinas;
}
screen+=WIDTH; xc+=sinas; yc+=cosas;
}
}
//This is the pure mathematical version of rotation and scaling.
//It is naturally slow since it has not be optimized to take advantage
//of the way computers currently operate. Nevertheless it can help
//some of you understand what is going on in the other routines.
void MathematicalRotateScale(float scale,
float angle)
{
//precompute the cosine and sine values used to speed things up
float cosas=cos(angle)*scale;
float sinas=sin(angle)*scale;
float xc, yc;
float tx, ty;
int x,y;
char *screen;
for (y=0;y<W_HEIGHT;y++)
{
for (x=0;x<W_WIDTH;x++)
{
//compute the center of the texture bitmap
xc=(float)(x-W_WIDTH_CENTER);
yc=(float)(y-W_HEIGHT_CENTER);
//compute the translation of x and y into texture map
//x' = x*cos(angle) - y*sin(angle) +160
//y' = x*sin(angle) + y*cos(angle) +100
tx=( (xc * cosas) - (yc * sinas) ) + (float)T_WIDTH_CENTER;
ty=( (xc * sinas) + (yc * cosas) ) + (float)T_HEIGHT_CENTER;
//compute the pixel on the composite screen buffer to draw to
screen=composite+(x+W_LEFT)+((y+W_TOP)*WIDTH);
//clip to black any texels that fall off of our 320x200 map
if( (tx<(float)T_LEFT) ||
(tx>=(float)T_RIGHT) ||
(ty<(float)T_TOP) ||
(ty>=(float)T_BOTTOM) )
*screen=0; //clipped to black
else
*screen=texture[ (int)(tx) + ( (int)(ty)*T_WIDTH) ]; //texel
}
}
}
//post bilinear antialiasing
void bilinear()
{
int line, x;
byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
for(line=HEIGHT-2;line>0;line--) {
for(x=W_WIDTH-2;x>0;x--) {
*p=(( (*p) + ( ( *(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH) ) >>2 ) )>>1);
p++;
}
p+=2*WIDTH_OFFSET+2;
}
}
//post trilinear antialiasing
void trilinear()
{
int line, x;
byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1;
for(line=HEIGHT-2;line>0;line--) {
for(x=W_WIDTH-2;x>0;x--) {
*p=(( (*p) + ( (*(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH)+*(p-WIDTH-1)+*(p-WIDTH+1)+*(p+WIDTH-1)+*(p+WIDTH+1)) >>3 ) )>>1);
p++;
}
p+=2*WIDTH_OFFSET+2;
}
}
//post hyperlinear? antialiasing. This is just an experiment.
void hyperlinear()
{
int line, x;
byte c;
byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1;
for(line=HEIGHT-2;line>0;line--) {
for(x=W_WIDTH-2;x>0;x--) {
c=(( (*p) + ( (*(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH)+*(p-WIDTH-1)+*(p-WIDTH+1)+*(p+WIDTH-1)+*(p+WIDTH+1)) >>3 ) )>>1);
*(p-WIDTH-1)=c;
*(p-WIDTH+1)=c;
*(p+WIDTH-1)=c;
*(p+WIDTH+1)=c;
p++;
}
p+=2*WIDTH_OFFSET+2;
}
}
//prime is the pixel in the center. fourth is one of the four sourrounding
//pixels in bilinear antialiasing.
void setup_matrix()
{
int match,diff;
int d;
int n;
int prime,derv;
int red,green,blue;
for(derv=0;derv<256;derv++) {
for(prime=0;prime<256;prime++) {
//compute the color component differences for red,
//green, and blue of the prime and the fourth.
//this rgb is the weighted average of the prime and the fourth.
red=(int)(palette[derv].red*.25+palette[prime].red*.75);
green=(int)(palette[derv].green*.25+palette[prime].green*.75);
blue=(int)(palette[derv].blue*.25+palette[prime].blue*.75);
//find the closet color in the 256 color palette
for(match=0,diff=3*256,n=0;n<256;n++) {
d=abs(palette[n].red-red)+abs(palette[n].green-green)+abs(palette[n].blue-blue);
if(d<diff) { match=n; diff=d; }
}
//add new entry to palette matrix
palette_matrix[derv*256+prime]=match;
}
printf(".");
}
printf("\n");
}
//post bilinear antialiasing
void color_bilinear()
{
int line, x;
byte c,cc;
byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
for(line=HEIGHT-2;line>0;line--) {
for(x=W_WIDTH-2;x>0;x--) {
c=*p;
c=palette_matrix[ c + ((*(p-1))<<8) ];
c=palette_matrix[ c + ((*(p+1))<<8) ];
c=palette_matrix[ c + ((*(p-WIDTH))<<8) ];
c=palette_matrix[ c + ((*(p+WIDTH))<<8) ];
*(p++)=c;
}
p+=2*WIDTH_OFFSET+2;
}
}
//this is the original color bilinear antialiasing routine.
//it works but is very slow.
void accurate_color_bilinear()
{
int n,match,diff;
int line,x;
int red,green,blue;
int d;
byte c;
byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
for(line=HEIGHT-2;line>0;line--) {
for(x=W_WIDTH-2;x>0;x--) {
//
c=*(p-1);
red=palette[c].red;
green=palette[c].green;
blue=palette[c].blue;
c=*(p+1);
red+=palette[c].red;
green+=palette[c].green;
blue+=palette[c].blue;
c=*(p-WIDTH);
red+=palette[c].red;
green+=palette[c].green;
blue+=palette[c].blue;
c=*(p+WIDTH);
red+=palette[c].red;
green+=palette[c].green;
blue+=palette[c].blue;
red=red>>2;
green=green>>2;
blue=blue>>2;
c=*p;
red+=palette[c].red;
green+=palette[c].green;
blue+=palette[c].blue;
red=red>>1;
green=green>>1;
blue=blue>>1;
//
for(match=0,diff=1000,n=0;n<256;n++) {
d=abs(palette[n].red-red)+abs(palette[n].green-green)+abs(palette[n].blue-blue);
if(d<diff) { match=n; diff=d; }
}
//
*p=match;
p++;
}
p+=2*WIDTH_OFFSET+2;
}
}
//copy the composite buffer to the VGA screen
void copycomposite()
{
memcpy(G_BASE,composite,WIDTH*HEIGHT);
}
//clear the composite buffer
void clearcomposite()
{
memset(composite,0,WIDTH*HEIGHT);
}
// "You had all of them on your side? didn't you?" --NIN
int main(int argc,char *argv[])
{
float angle=PI/256.0;
float angle_v=-PI/128.0;
float scale=1.05;
int n;
int alias=0, render=0, grayscale=TRUE;
int key='~',key2=0; //so as not to trip up the arrow keys below
int frames=0;
mode_text();
printf("Scaling/Rotation/Antialiasing Prototyper by Minimalist 1995-1996.\n");
// printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
#ifdef __WATCOMC__
printf("Using 32-bit compiler Watcom C version %d.%d.\n\n",
(__WATCOMC__)/100,(__WATCOMC__%100));
#endif
//you did specify a filename didn't you?
if(argc!=2)
{
printf("Use: ALIASWC 'filename.bmp'\n");
return(FAILURE);
}
printf("Allocating palette.\n");
palette=(void *)malloc(3*256);
if(palette==NULL) {
mode_text();
// printf("Not enough memory (%lu) for palette.\n",farcoreleft());
exit(FAILURE);
}
printf("Allocating texture.\n");
texture=(char *)malloc(T_WIDTH*T_WIDTH);
if(texture==NULL) {
mode_text();
// printf("Not enough memory (%lu) for texture map.\n",farcoreleft());
exit(FAILURE);
}
//create a composite buffer (off-screen double buffer)
printf("Allocating composite buffer.\n");
composite=(char *)malloc(WIDTH*HEIGHT);
if(composite==NULL) {
mode_text();
// printf("Not enough memory (%lu) for composite buffer.\n",farcoreleft());
exit(FAILURE);
}
//initialize our table of n*320
printf("Allocating y320.\n Computing y[0,%d).\n",HEIGHT);
y320=(int *)malloc(sizeof(int)*HEIGHT);
if(y320==NULL) {
mode_text();
// printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
exit(FAILURE);
}
for(n=0;n<HEIGHT;n++) y320[n]=n*WIDTH;
printf("Load image [%s].\n",argv[1]);
if(LoadTestImage(argv[1])==FAILURE)
{
mode_text();
printf("The file %s does not exist.\n",argv[1]);
return(FAILURE);
}
printf("Allocating palette_matrix.\n Computing Color Bilinear Antialiasing matrix");
palette_matrix=(byte *)malloc(256*256);
if(palette_matrix==NULL) {
mode_text();
// printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
exit(FAILURE);
}
setup_matrix();
//inpho
mode_text();
printf("Scaling/Rotation/Antialiasing Prototyper 3 by Minimalist 1995-1996.\n");
// printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
#ifdef __WATCOMC__
printf("Using 32-bit compiler Watcom C version %d.%d.\n\n",
(__WATCOMC__)/100,(__WATCOMC__%100));
#endif
// printf("Memory %u. Stack %u.\n",_memavl(),stackavail());
/*
if(_control87)
printf("FPU:%d87.",_8087);
else
printf("No FPU.");
*/
//the propaganda
printf("This program requires at least a 486 with an integrated 387 grade FPU\n");
printf("and the DOS Extender DOS4GW.EXE or a compatible.\n");
printf("You may use any of the following keys:\n");
printf(" ESC will exit the program\n");
printf(" C Color antialiasing\n");
printf(" G Fast grayscale antialiasing\n");
printf("Scaling and Rotation:\n");
printf(" I Integer fixed-point Optimized\n");
printf(" F Floating-point Optimized\n");
printf(" M Mathematical floating-point\n");
printf("Antialiasing Filters:\n");
printf(" N No Antialiasing\n");
printf(" B Post Bilinear Antialiasing\n");
printf(" T Post Trilinear Antialiasing (GRAYSCALE ONLY)\n");
printf(" H Post um... ghosting/Antialiasing? (GRAYSCALE ONLY)\n");
printf(" A Accurate Bilinear Color Antialiasing (COLOR ONLY) (SLOW!)\n");
printf("To rotate use left/right arrows. To scale use up/down arrows.\n");
printf("Pressing Ctrl w/ arrows will increase speed. Use BACKSPACE to stop.\n\n");
//wait for windows to quit thrashing the hard drive...
printf("Press any key (except ESC) to start...\n");
while (!kbhit()); getch();
//set things up
mode_graphic();
clearcomposite();
setup_fps();
show_colors();
change_timer();
//the main loop
while (key!=27) {
if(kbhit()) {
key=toupper(getch());
switch (key) {
//internal yazzie testing frame for...
//and sissy
case 'S':
angle-=PI/4.0;
angle_v=0.0;
break;
//and susy honey
case 'U':
angle+=PI/4.0;
angle_v=0.0;
break;
//and prissy
case 'Z':
scale=0.5;
angle=PI/2.0;
angle_v=-0.1;
break;
//and yazzie :)
case 'Y':
angle=0.0;
angle_v=0.0;
scale=1.0;
break;
case 'I': render=0; break;
case 'F': render=1; break;
case 'M': render=2; break;
case 'W': render=3; break;
case 'N': alias=1; break;
case 'B': alias=2; break;
case 'T':
case 'A': alias=3; break;
case 'H': alias=4; break;
case 'C': grayscale=FALSE; break;
case 'G': grayscale=TRUE; break;
case 0:
key2=getch();
switch (key2) {
//rotation
case 75: angle_v+=PI/256.0; break; //left arrow
case 77: angle_v-=PI/256.0; break; //right arrow
case 115: angle_v+=PI/32.0; break; //left arrow
case 116: angle_v-=PI/32.0; break; //right arrow
//scale
case 72: scale-=0.05; break;
case 80: scale+=0.05; break;
case 141: scale-=0.5; break;
case 145: scale+=0.5; break;
}
break;
}
}
switch (render) {
case 0: FixedRotateScale(scale,angle); break;
case 1: FloatRotateScale(scale,angle); break;
case 2: MathematicalRotateScale(scale,angle); break;
}
switch (grayscale) {
case FALSE: {
switch (alias) {
//case 1: do nothing....
case 2: color_bilinear(); break;
case 3: accurate_color_bilinear(); break;
}
break;
case TRUE: {
switch (alias) {
//case 1: do nothing....
case 2: bilinear(); break;
case 3: trilinear(); break;
case 4: hyperlinear(); break;
}
break;
}
}
}
copycomposite(); //show us the composite buffer!
angle+=angle_v;
if(angle>2*PI) angle-=2*PI; //bound our angle...
if(angle<-2*PI) angle+=2*PI;
//do the FPS calcing
frames++;
if(second_flag) { //been a second yet?
print_fps(frames); //yes, so see how many frames we've done in that time.
second_flag=FALSE;
frames=0; //and the frames
}
}
//restore things to normal
restore_timer();
free(composite);
free(palette);
free(texture);
free(y320);
free(palette_matrix);
//parting words....
mode_text();
printf("By Minimalist (Lewis A. Sellers) 1995-96. Part of the C/Pascal/Asm package.\n");
printf("To contact, email: lsellers@1stresource.com (shortly to be lsellers@usit.net).\n");
printf("or drop by http://www.dwc.edu/grail, site of Grail Operating System Project.\n\n");
printf("#coders home page: http://www.realtime.net/~dlinvill/coders/index.html\n\n");
printf("Psst. Testing out the original code or modification you did to it? Then press\n");
printf("Z to set a standard scale and rotation factor. On a 486dx4 100mhz 256kb cache\n");
printf("60ns DRAM, and an awful PCI Trio32 S3 graphics card:\n");
printf(" I=~43fps F=~7fps M=~5fps\n");
printf(" I/Grayscale Bilinear=~27fps Trilinear=~23fps Hyperlinear=~21.5fps\n");
printf(" I/Color Bilinear=~19fps\n\n");
printf(" 'It was men like me that built the bomb.' --paraphrased, T2\n\n");
return(SUCCESS);
}
//cute trick of mine for single file programs
//int lines() { return __LINE__+1; }